home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / rip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-30  |  16.9 KB  |  695 lines

  1. /* This file contains code to implement the Routing Information Protocol (RIP)
  2.  * and is derived from 4.2BSD code. Mike Karels of Berkeley has stated on
  3.  * TCP-IP that the code may be freely used as long as UC Berkeley is
  4.  * credited. (Well, here's some credit :-). AGB 4-28-88
  5.  
  6.  * Further documentation on the RIP protocol is now available in Charles
  7.  * Hedrick's draft RFC, as yet unnumbered. AGB 5-6-88
  8.  *
  9.  * The RIP RFC has now been issued as RFC1058. AGB 7-23-88
  10.  *
  11.  * Code gutted and substantially rewritten. KA9Q 9/89
  12.  *
  13.  * Mods by PA0GRI
  14.  */
  15. #include "global.h"
  16. #include "config.h"
  17. #include "mbuf.h"
  18. #include "netuser.h"
  19. #include "udp.h"
  20. #include "timer.h"
  21. #include "iface.h"
  22. #include "ip.h"
  23. #include "internet.h"
  24. #include "rip.h"
  25. #include "arp.h"
  26.  
  27. #ifdef RIP
  28.  
  29. struct rip_stat Rip_stat;
  30. int16 Rip_trace;
  31. int Rip_merge;
  32. int32 Rip_ttl = RIP_TTL;
  33. struct rip_list *Rip_list;
  34. struct udp_cb *Rip_cb;
  35.  
  36. struct rip_refuse *Rip_refuse;
  37.  
  38. static void rip_rx __ARGS((struct iface *iface,struct udp_cb *sock,int cnt));
  39. static void proc_rip __ARGS((struct iface *iface,int32 gateway,
  40.     struct rip_route *ep));
  41. static char *putheader __ARGS((char *cp,char command,char version));
  42. static char *putentry __ARGS((char *cp,int16 fam,int32 target,int32 metric));
  43. void rip_shout __ARGS((void *p));
  44. static void send_routes __ARGS((int32 dest,int16 port,int split,int trig,
  45.     int us));
  46.  
  47. /* Send RIP CMD_RESPONSE packet(s) to the specified rip_list entry */
  48. void
  49. rip_shout(p)
  50. void *p;
  51. {
  52.     register struct rip_list *rl;
  53.  
  54.     rl = (struct rip_list *)p;
  55.     stop_timer(&rl->rip_time);
  56.     send_routes(rl->dest,RIP_PORT,(rl->flags & RIP_SPLIT),0,
  57.         rl->flags & RIP_US);
  58.     set_timer(&rl->rip_time,rl->interval*1000L);
  59.     start_timer(&rl->rip_time);
  60. }
  61.  
  62. /* Send the routing table. */
  63. static void
  64. send_routes(dest,port,split,trig,us)
  65. int32 dest;        /* IP destination address to send to */
  66. int16 port;
  67. int split;        /* Do split horizon? */
  68. int trig;        /* Send only triggered updates? */
  69. int us;            /* Include our address in update */
  70. {
  71.     char *cp;
  72.     int i,bits,numroutes,maxroutes;
  73.     int16 pktsize;
  74.     struct mbuf *bp;
  75.     struct route *rp;
  76.     struct socket lsock,fsock;
  77.     struct iface *iface;
  78.  
  79.     if((rp = rt_lookup(dest)) == NULLROUTE)
  80.         return;    /* No route exists, can't do it */
  81.     iface = rp->iface;
  82.  
  83.     /* Compute maximum packet size and number of routes we can send */
  84.     pktsize = ip_mtu(dest) - IPLEN;
  85.     pktsize = min(pktsize,MAXRIPPACKET);
  86.     maxroutes = (pktsize - RIPHEADER) / RIPROUTE;
  87.  
  88.     lsock.address = INADDR_ANY;
  89.     lsock.port = RIP_PORT;
  90.     fsock.address = dest;
  91.     fsock.port = port;
  92.  
  93.     /* Allocate space for a full size RIP packet and generate header */
  94.     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  95.         return; 
  96.     numroutes = 0;
  97.     cp = putheader(bp->data,RIPCMD_RESPONSE,RIPVERSION);
  98.  
  99.        /* Emit route to ourselves, if requested */
  100.        if(us){
  101.                cp = putentry(cp,RIP_IPFAM,iface->addr,0);
  102.                numroutes++;
  103.        }
  104.  
  105.     /* Emit default route, if appropriate */
  106.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)
  107.      && (!trig || (R_default.flags & RTTRIG))){
  108.         if(!split || iface != R_default.iface){
  109.              cp = putentry(cp,RIP_IPFAM,0,R_default.metric);
  110.             numroutes++;
  111.         } else if(trig){
  112.             cp = putentry(cp,RIP_IPFAM,0,RIP_INFINITY);
  113.             numroutes++;
  114.         }
  115.     }
  116.     for(bits=0;bits<32;bits++){
  117.         for(i=0;i<HASHMOD;i++){
  118.             for(rp = Routes[bits][i];rp != NULLROUTE;rp=rp->next){
  119.                 if((rp->flags & RTPRIVATE)
  120.                  || (trig && !(rp->flags & RTTRIG))) 
  121.                     continue;
  122.  
  123.                 if(numroutes >= maxroutes){
  124.                     /* Packet full, flush and make another */
  125.                     bp->cnt = RIPHEADER + numroutes * RIPROUTE;
  126.                     send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  127.                     Rip_stat.output++;
  128.                     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  129.                         return; 
  130.                     numroutes = 0;
  131.                     cp = putheader(bp->data,RIPCMD_RESPONSE,RIPVERSION);
  132.                 }
  133.                 if(!split || iface != rp->iface){
  134.                      cp = putentry(cp,RIP_IPFAM,rp->target,rp->metric);
  135.                     numroutes++;
  136.                 } else if(trig){
  137.                      cp = putentry(cp,RIP_IPFAM,rp->target,RIP_INFINITY);
  138.                     numroutes++;
  139.                 }
  140.             }
  141.         }
  142.     }
  143.     if(numroutes != 0){
  144.         bp->cnt = RIPHEADER + numroutes * RIPROUTE;
  145.         send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  146.         Rip_stat.output++;
  147.     } else {
  148.         free_p(bp);
  149.     }
  150. }
  151. /* Add an entry to the rip broadcast list */
  152. int
  153. rip_add(dest,interval,flags)
  154. int32 dest;
  155. int32 interval;
  156. char flags;
  157. {
  158.     register struct rip_list *rl;
  159.     struct route *rp;
  160.  
  161.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  162.         if(rl->dest == dest)
  163.             return 0;
  164.  
  165.     if((rp = rt_lookup(dest)) == NULLROUTE){
  166.         tprintf("%s is unreachable\n",inet_ntoa(dest));
  167.         return 1;
  168.     }
  169.     /* get a chunk of memory for the rip interface descriptor */
  170.     rl = (struct rip_list *)callocw(1,sizeof(struct rip_list));
  171.  
  172.     /* tack this record on as the first in the list */
  173.     rl->next = Rip_list;
  174.     if(rl->next != NULLRL)
  175.         rl->next->prev = rl;
  176.     Rip_list = rl;
  177.  
  178.     rl->dest = dest;
  179.  
  180.     /* and the interface ptr, tick interval and flags */
  181.     rl->iface = rp->iface;
  182.     rl->interval = interval;
  183.     rl->flags = flags;
  184.  
  185.     /* and set up the timer stuff */
  186.     set_timer(&rl->rip_time,interval*1000L);
  187.     rl->rip_time.func = rip_shout;
  188.     rl->rip_time.arg = rl;
  189.     start_timer(&rl->rip_time);
  190.     return 0;
  191. }
  192.  
  193. /* add a gateway to the rip_refuse list which allows us to ignore their
  194.  * advertisements
  195. */
  196. int
  197. riprefadd(gateway)
  198. int32 gateway;
  199. {
  200.     register struct rip_refuse *rl;
  201.  
  202.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  203.         if(rl->target == gateway)
  204.             return 0;    /* Already in table */
  205.   
  206.  
  207.     /* get a chunk of memory for the rip interface descriptor */
  208.     rl = (struct rip_refuse *)callocw(1,sizeof(struct rip_refuse));
  209.  
  210.     /* tack this record on as the first in the list */
  211.     rl->next = Rip_refuse;
  212.     if(rl->next != NULLREF)
  213.         rl->next->prev = rl;
  214.     Rip_refuse = rl;
  215.  
  216.     /* fill in the gateway to ignore */
  217.     rl->target = gateway;
  218.     return 0;
  219. }
  220.  
  221. /* drop a RIP target */
  222. int
  223. rip_drop(dest)
  224. int32    dest;
  225. {
  226.     register struct rip_list *rl;
  227.  
  228.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  229.         if(rl->dest == dest)
  230.             break;
  231.  
  232.     /* leave if we didn't find it */
  233.     if(rl == NULLRL)
  234.         return 0;
  235.  
  236.     /* stop the timer */
  237.     stop_timer(&rl->rip_time);
  238.  
  239.     /* Unlink from list */
  240.     if(rl->next != NULLRL)
  241.         rl->next->prev = rl->prev;
  242.     if(rl->prev != NULLRL)
  243.         rl->prev->next = rl->next;
  244.     else
  245.         Rip_list = rl->next;
  246.  
  247.     /* and deallocate the descriptor memory */
  248.     free((char *)rl);
  249.     return 0;
  250. }
  251.  
  252. /* drop a RIP-refuse target from the rip_refuse list */
  253. int
  254. riprefdrop(gateway)
  255. int32 gateway;
  256. {
  257.     register struct rip_refuse *rl;
  258.     
  259.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  260.         if(rl->target == gateway)
  261.             break;
  262.   
  263.     /* leave if we didn't find it */
  264.     if(rl == NULLREF)
  265.         return 0;
  266.  
  267.     /* Unlink from list */
  268.     if(rl->next != NULLREF)
  269.         rl->next->prev = rl->prev;
  270.     if(rl->prev != NULLREF)
  271.         rl->prev->next = rl->next;
  272.     else
  273.         Rip_refuse = rl->next;
  274.  
  275.     /* and deallocate the structure memory */
  276.     free((char *)rl);
  277.     return 0;
  278. }
  279.  
  280. /* function to output a RIP CMD_RESPONSE packet for the rip_trigger list */
  281. void
  282. rip_trigger()
  283. {
  284.     register struct rip_list *rl;
  285.     int bits,i;
  286.     struct route *rp;
  287.  
  288.     for(rl=Rip_list;rl != NULLRL;rl = rl->next){
  289.         send_routes(rl->dest,RIP_PORT,(rl->flags & RIP_SPLIT),1,0);
  290.     }
  291.     /* Clear the trigger list */
  292.     R_default.flags &= ~RTTRIG;
  293.     for(bits=0;bits<32;bits++){
  294.         for(i=0;i<HASHMOD;i++){
  295.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  296.                 rp->flags &= ~RTTRIG;
  297.             }
  298.         }
  299.     }
  300. }
  301.  
  302. /* Start RIP agent listening at local RIP UDP port */
  303. int
  304. rip_init()
  305. {
  306.     struct socket lsock;
  307.  
  308.     lsock.address = INADDR_ANY;
  309.     lsock.port = RIP_PORT;
  310.  
  311.     if(Rip_cb == NULLUDP)
  312.         Rip_cb = open_udp(&lsock,rip_rx);
  313.  
  314.     return 0;
  315. }
  316.  
  317. /* Process RIP input received from 'interface'. */
  318. static void
  319. rip_rx(iface,sock,cnt)
  320. struct iface *iface;
  321. struct udp_cb *sock;
  322. int cnt;
  323. {
  324.     struct mbuf *bp;
  325.     struct socket fsock;
  326.     int cmd;
  327.     register struct rip_refuse *rfl;
  328.     struct rip_route entry;
  329.     struct route *rp;
  330.  
  331.     /* receive the RIP packet */
  332.     recv_udp(sock,&fsock,&bp);
  333.  
  334.     /* increment the rcvd cnt */
  335.     Rip_stat.rcvd++;
  336.  
  337.     /* check the gateway of this packet against the rip_refuse list and
  338.      * discard it if a match is found
  339.      */
  340.     for(rfl=Rip_refuse;rfl != NULLREF;rfl = rfl->next){
  341.         if(fsock.address == rfl->target){
  342.             Rip_stat.refusals++;
  343.             if(Rip_trace > 1)
  344.                 printf("RIP refused from %s\n",
  345.                  inet_ntoa(fsock.address));
  346.             free_p(bp);
  347.             return;
  348.          }
  349.     }
  350.     cmd = PULLCHAR(&bp);
  351.     /* Check the version of the frame */
  352.     if(PULLCHAR(&bp) != RIPVERSION){
  353.         free_p(bp);
  354.         Rip_stat.version++;
  355.         return;
  356.     }
  357.     switch(cmd){
  358.     case RIPCMD_RESPONSE:
  359.         if(Rip_trace > 1)
  360.             printf("RIPCMD_RESPONSE from %s \n",inet_ntoa(fsock.address));
  361.  
  362.         Rip_stat.response++;
  363.         (void)pull16(&bp);    /* remove one word of padding */
  364.         while(len_p(bp) >= RIPROUTE){
  365.             pullentry(&entry,&bp);
  366.             proc_rip(iface,fsock.address,&entry);
  367.         }
  368.         /* If we can't reach the sender of this update, or if
  369.          * our existing route is not through the interface we
  370.          * got this update on, add him as a host specific entry
  371.          */
  372.         if((rp = rt_blookup(fsock.address,32)) != NULLROUTE){
  373.             /* Host-specific route already exists, refresh it */
  374.             start_timer(&rp->timer);
  375.         } else if((rp = rt_lookup(fsock.address)) == NULLROUTE
  376.          || rp->iface != iface){
  377.             entry.addr_fam = RIP_IPFAM;
  378.             entry.target = fsock.address;
  379.             entry.metric = 0; /* will get incremented to 1 */
  380.             proc_rip(iface,fsock.address,&entry);
  381.         }
  382.         if(Rip_merge)
  383.             rt_merge(Rip_trace);
  384.         rip_trigger();
  385.         break;
  386.     case RIPCMD_REQUEST:
  387.         if(Rip_trace > 1)
  388.             printf("RIPCMD_REQUEST\n");
  389.  
  390.         Rip_stat.request++;
  391.         /* For now, just send the whole table with split horizon
  392.          * enabled when the source port is RIP_PORT, and send
  393.          * the whole table with split horizon disable when another
  394.          * source port is used. This should be replaced with a more
  395.          * complete implementation that checks for non-global requests
  396.          */
  397.         if(fsock.port == RIP_PORT)
  398.             send_routes(fsock.address,fsock.port,1,0,1);
  399.         else
  400.             send_routes(fsock.address,fsock.port,0,0,1);
  401.         break;
  402.     default:
  403.         if(Rip_trace > 1)
  404.             printf("RIPCMD: Unknown Type\n");
  405.  
  406.         Rip_stat.unknown++;
  407.         break;
  408.     } /* switch */
  409.     free_p(bp);
  410. }
  411. /* Apply a set of heuristics for determining the number of significant bits
  412.  * (i.e., the address mask) in the target address. Needed since RIP doesn't
  413.  * include the address mask for each entry.
  414.  */
  415. int
  416. nbits(target)
  417. int32 target;
  418. {
  419.     int bits;
  420.  
  421.     if(target == 0)
  422.         return 0;    /* Special case: 0.0.0.0 is the default route */
  423.  
  424.     /* Check the host-part bytes of
  425.      * the address to check for byte-wide zeros
  426.      * which we'll consider to be subnet routes.
  427.      * e.g.    44.80.0.0 will be considered to be equal to 44.80/16
  428.      * whereas 44.80.1.0 will be considered to be 44.80.1/24
  429.      */
  430.     switch (hibyte(hiword(target)) >> 6) {
  431.     case 3:    /* Class C address */
  432.         /*is it a host address ? i.e. are there any 1's in the
  433.          * host part ?
  434.          */
  435.         if(target & 0xff)
  436.             bits = 32;
  437.         else
  438.             bits = 24;
  439.         break;
  440.     case 2:  /* Class B address */
  441.         if(target & 0xff)
  442.             bits = 32;
  443.         else if(target & 0xff00)
  444.             bits = 24;
  445.         else
  446.             bits = 16;
  447.         break;
  448.         case 0:      /* Class A address */
  449.         case 1:
  450.         if(target & 0xff)
  451.             bits = 32;
  452.         else if(target & 0xff00)
  453.             bits = 24;
  454.         else if(target & 0xff0000)
  455.             bits = 16;
  456.         else
  457.             bits = 8;
  458.     }
  459.  
  460.     return bits;
  461. }
  462. /* Remove and process a RIP response entry from a packet */
  463. static void
  464. proc_rip(iface,gateway,ep)
  465. struct iface *iface;
  466. int32 gateway;
  467. register struct rip_route *ep;
  468. {
  469.     int32 interval;
  470.     unsigned int bits;
  471.     register struct route *rp;
  472.     struct rip_list *rl;
  473.     int add = 0;    /* action flags */
  474.     int drop = 0;
  475.     int trigger = 0;
  476.  
  477.     if(ep->addr_fam != RIP_IPFAM) {
  478.         /* Skip non-IP addresses */
  479.         if(Rip_trace > 1)
  480.             printf("RIP_rx: Not an IP RIP packet !\n");
  481.         Rip_stat.addr_family++;
  482.         return;
  483.     }
  484.     /* Guess at the mask, since it's not explicit */
  485.     bits = nbits(ep->target);
  486.  
  487.     /* Don't ever add a route to myself through somebody! */
  488.     if(bits == 32 && ismyaddr(ep->target) != NULLIF){
  489.         if(Rip_trace > 1){
  490.             printf("route to self: %s %ld\n",
  491.              inet_ntoa(ep->target),ep->metric);
  492.         }
  493.         return;
  494.     }
  495.     /* Update metric to reflect link cost */
  496.     ep->metric++;
  497.     ep->metric = min(ep->metric,RIP_INFINITY);
  498.  
  499.     /* Find existing entry, if any */
  500.     rp = rt_blookup(ep->target,bits);
  501.  
  502.     /* Don't touch private routes */
  503.     if(rp != NULLROUTE && (rp->flags & RTPRIVATE))
  504.         return;
  505.  
  506.     if(rp == NULLROUTE){
  507.         if(ep->metric < RIP_INFINITY){
  508.             /* New route; add it and trigger an update */
  509.             add++;
  510.             trigger++;
  511.         }
  512.     } else if(rp->metric == RIP_INFINITY){
  513.         /* Route is in hold-down; ignore this guy */
  514.         if(Rip_trace > 0){
  515.             printf("ignored (hold-down): %s %lu\n",
  516.              inet_ntoa(ep->target),ep->metric);
  517.         }
  518.     } else if(rp->gateway == gateway && rp->iface == iface){
  519.         /* This is the gateway for the entry we already have;
  520.          * restart the timer
  521.          */
  522.         start_timer(&rp->timer);
  523.         if(rp->metric != ep->metric){
  524.             /* Metric has changed. Update it and trigger an
  525.              * update. If route has become unavailable, start
  526.              * the hold-down timeout.
  527.              */
  528.             if(Rip_trace){
  529.                 printf("metric change: %s %lu -> %lu\n",
  530.                  inet_ntoa(ep->target),rp->metric,ep->metric);
  531.             }
  532.             if(ep->metric == RIP_INFINITY)
  533.                 rt_timeout(rp);    /* Enter hold-down timeout */
  534.             else
  535.                 rp->metric = ep->metric;
  536.             trigger++;
  537.         }
  538.     } else {
  539.         /* Entry is from a different gateway than the current route */
  540.         if(ep->metric < rp->metric){
  541.             /* Switch to a new gateway */
  542.             if(Rip_trace > 0){
  543.                 printf("metric better: %s %lu\n",
  544.                  inet_ntoa(ep->target),ep->metric);
  545.             }
  546.             drop++;
  547.             add++;
  548.             trigger++;
  549.         } else {
  550.             /* Metric is no better, stay with current route */
  551.             if(Rip_trace > 1){
  552.                 printf("metric not better: %s %lu\n",
  553.                  inet_ntoa(ep->target),ep->metric);
  554.             }
  555.         }
  556.     }
  557.     if(drop){
  558.         /* Switching to a better gateway; delete old entry */
  559.         if(Rip_trace){
  560.             printf("route drop [%s]/%u",
  561.              inet_ntoa(ep->target),bits);
  562.             if(rp != NULLROUTE)
  563.                 printf(" %s %s %lu",rp->iface->name,
  564.                  inet_ntoa(rp->gateway),rp->metric);
  565.             printf("\n");
  566.         }
  567.         rt_drop(ep->target,bits);
  568.     }
  569.     if(add){
  570.         /* Add a new entry */
  571.         interval = Rip_ttl;
  572.         for(rl=Rip_list; rl != NULLRL; rl = rl->next){
  573.             if(rl->iface == iface){
  574.                 interval = rl->interval * 4;
  575.                 break;
  576.             }
  577.         }
  578.         if(Rip_trace > 0){
  579.             printf("route add [%s]/%u %s",inet_ntoa(ep->target),
  580.              bits,iface->name);
  581.             printf(" [%s] %u\n",inet_ntoa(gateway),
  582.              (int)ep->metric);
  583.         }
  584.         rp = rt_add(ep->target,(unsigned) bits,gateway,iface,
  585.          (int) ep->metric,interval,0);
  586.     }
  587.     /* If the route changed, mark it for a triggered update */
  588.     if(trigger){
  589.         rp->flags |= RTTRIG;
  590.     }
  591. }
  592. /* Send a RIP request packet to the specified destination */
  593. int
  594. ripreq(dest,replyport)
  595. int32 dest;
  596. int16 replyport;
  597. {
  598.     struct mbuf *bp;
  599.     struct socket lsock,fsock;
  600.     char *cp;
  601.  
  602.     lsock.address = INADDR_ANY;
  603.     lsock.port = replyport;
  604.  
  605.     /* if we were given a valid dest addr, ask it (the routers on that net)
  606.      * for a default gateway
  607.      */
  608.     if(dest == 0)
  609.         return 0;
  610.  
  611.     fsock.address = dest;
  612.     fsock.port = RIP_PORT;
  613.  
  614.     /* Send out one RIP Request packet as a broadcast to 'dest'  */
  615.     if((bp = alloc_mbuf(RIPHEADER + RIPROUTE)) == NULLBUF)
  616.         return -1;
  617.  
  618.     cp = putheader(bp->data,RIPCMD_REQUEST,RIPVERSION);
  619.     cp = putentry(cp,0,0L,RIP_INFINITY);
  620.     bp->cnt = RIPHEADER + RIPROUTE;
  621.     send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
  622.     Rip_stat.output++;
  623.     return 0;
  624. }
  625.  
  626. /* Write the header of a RIP packet */
  627. static char *
  628. putheader(cp,command,version)
  629. register char *cp;
  630. char command;
  631. char version;
  632. {
  633.     *cp++ = command;
  634.     *cp++ = version;
  635.     return put16(cp,0);
  636. }
  637.  
  638. /* Write a single entry into a rip packet */
  639. static char *
  640. putentry(cp,fam,target,metric)
  641. register char *cp;
  642. int16 fam;
  643. int32 target;
  644. int32 metric;
  645. {
  646.     cp = put16(cp,fam);
  647.     cp = put16(cp,0);
  648.     cp = put32(cp,target);
  649.     cp = put32(cp,0L);
  650.     cp = put32(cp,0L);
  651.     return put32(cp,metric);
  652. }
  653. /* Route timeout handler. If route has already been marked for deletion
  654.  * then delete it. Otherwise mark for deletion and restart timer.
  655.  */
  656. void
  657. rt_timeout(s)
  658. void *s;
  659. {
  660.     register struct route *rp = (struct route *)s;
  661.  
  662.     stop_timer(&rp->timer);
  663.     if(rp->metric < RIP_INFINITY){
  664.         rp->metric = RIP_INFINITY;
  665.         if(dur_timer(&rp->timer) == 0)
  666.             set_timer(&rp->timer,Rip_ttl*1000L);
  667.         /* wait 2/3 of timeout before garbage collect */
  668.         set_timer(&rp->timer,dur_timer(&rp->timer)*2/3);
  669.         rp->timer.func = (void *)rt_timeout;
  670.         rp->timer.arg = (void *)rp;
  671.         start_timer(&rp->timer);
  672.         /* Route changed; mark it for triggered update */
  673.         rp->flags |= RTTRIG;
  674.         rip_trigger();
  675.     } else {
  676.         rt_drop(rp->target,rp->bits);
  677.     }
  678. }
  679. #endif /* RIP */
  680.  
  681. void
  682. pullentry(ep,bpp)
  683. register struct rip_route *ep;
  684. struct mbuf **bpp;
  685. {
  686.     ep->addr_fam = pull16(bpp);
  687.     (void)pull16(bpp);
  688.     ep->target = pull32(bpp);
  689.     (void)pull32(bpp);
  690.     (void)pull32(bpp);
  691.     ep->metric = pull32(bpp);
  692. }
  693.  
  694.  
  695.